home *** CD-ROM | disk | FTP | other *** search
/ Graphics Plus / Graphics Plus.iso / general / raytrace / rayshade / graphtal.lzh / Graphtal.Amiga / rcString.C < prev    next >
C/C++ Source or Header  |  1993-08-26  |  5KB  |  259 lines

  1. /*
  2.  * rcString.C - reference counted string class.
  3.  *
  4.  * Copyright (C) 1992, Christoph Streit (streit@iam.unibe.ch)
  5.  *                     Igor Metz (metz@iam.unibe.ch)
  6.  *                     University of Berne, Switzerland
  7.  * All rights reserved.
  8.  *
  9.  * This software may be freely copied, modified, and redistributed
  10.  * provided that this copyright notice is preserved on all copies.
  11.  *
  12.  * You may not distribute this software, in whole or in part, as part of
  13.  * any commercial product without the express consent of the authors.
  14.  *
  15.  * There is no warranty or other guarantee of fitness of this software
  16.  * for any purpose.  It is provided solely "as is".
  17.  *
  18.  */
  19.  
  20. #ifdef AMIGA_GCC
  21.     #include "string.h"
  22. #endif
  23.  
  24. #include <iostream.h>
  25. #include "rcString.h"
  26. #include "Error.h"
  27.  
  28. //___________________________________________________________ rcStringRep
  29. //
  30. // reference counted rcString representation
  31.  
  32. class rcStringRep 
  33. {
  34.   friend class rcString;
  35.  
  36. public:
  37.   rcStringRep(char);
  38.   rcStringRep(const char*);
  39.   ~rcStringRep();
  40.   
  41. private:
  42.   char* str;
  43.   int len;
  44.   int count;
  45.  
  46. private:
  47.   rcStringRep(_Char_p_*);
  48.   void ref();
  49.   void deref();
  50. };
  51.  
  52. inline rcStringRep::rcStringRep(char c) {
  53.   str = new char[2]; str[0] = c; str[1] = '\0'; 
  54.   count = len = 1;
  55. }
  56.  
  57. inline rcStringRep::rcStringRep(const char* s) {
  58.   len = strlen(s);
  59.   str = new char[len+1];
  60.   strcpy(str, s);
  61.   count = 1;
  62. }
  63.  
  64. inline rcStringRep::~rcStringRep() {
  65.   delete [] str; 
  66. }
  67.  
  68. inline rcStringRep::rcStringRep(_Char_p_* r) { 
  69.   str = *r; count = 1; len = strlen(str); 
  70. }
  71.  
  72. inline void rcStringRep::ref() {
  73.   count++;
  74. }
  75.  
  76. inline void rcStringRep::deref() {
  77.   if (--count <= 0) delete this;
  78. }
  79.  
  80. //___________________________________________________________ rcString
  81.  
  82. // constructors and destructors
  83.  
  84. rcString::rcString() {
  85.   rep = new rcStringRep(""); 
  86. }
  87.  
  88. rcString::rcString(char c) {
  89.   rep = new rcStringRep(c); 
  90. }
  91.  
  92. rcString::rcString(const char* s) { 
  93.   rep = new rcStringRep(s); 
  94. }
  95.  
  96. rcString::rcString(const rcString &s) { 
  97.   s.rep->ref(); rep = s.rep; 
  98. }
  99.  
  100. rcString::rcString(_Char_p_* r) { 
  101.   rep = new rcStringRep(r); 
  102. }
  103.  
  104. rcString::~rcString() { 
  105.   rep->deref(); 
  106. }
  107.  
  108. // status reports
  109.  
  110. unsigned rcString::length() const {
  111.   return rep->len; 
  112. }
  113.  
  114. int rcString::empty() const { 
  115.   return rep->len == 0; 
  116. }
  117.  
  118. const char* rcString::chars() const {
  119.   return rep->str; 
  120. }
  121.  
  122. rcString::operator const char*() const {
  123.   return rep->str; 
  124. }
  125.  
  126. // element extraction and substring
  127.  
  128. char& rcString::operator[](unsigned i)
  129. {
  130.   if (i>=length())
  131.     Error(ERR_PANIC, "rcString::operator[] index out of range");
  132.   /*
  133.    * Copy on write!
  134.    */
  135.   if (rep->count > 1) {
  136.     rep->deref();
  137.     rep = new rcStringRep(rep->str);
  138.   }
  139.  
  140.   return rep->str[i];
  141. }
  142.  
  143. char rcString::operator[](unsigned i) const
  144. {
  145.   if (i>=length())
  146.     Error(ERR_PANIC, "rcString::operator[] index out of range");
  147.  
  148.   return rep->str[i];
  149. }
  150.  
  151. rcString rcString::operator()(unsigned i, unsigned j)
  152. {
  153.   if (j<i || i>=length() || j>=length())
  154.     Error(ERR_PANIC, "rcString::operator() index out of range");
  155.  
  156.   char* buf = new char[j-i+1];
  157.   strncpy(buf, rep->str+i, j-i);
  158.   buf[j-i] = '\0';
  159.  
  160.   return rcString(&buf);
  161. }
  162.  
  163. // assignment
  164.  
  165. const rcString& rcString::operator=(char c)
  166. {
  167.   rep->deref();
  168.   rep = new rcStringRep(c);
  169.  
  170.   return *this;
  171. }
  172.  
  173. const rcString& rcString::operator=(const char* s)
  174. {
  175.   rep->deref();
  176.   rep = new rcStringRep(s);
  177.  
  178.   return *this;
  179. }
  180.  
  181. const rcString& rcString::operator=(const rcString& s)
  182. {
  183.   s.rep->ref();
  184.   rep->deref();
  185.   rep = s.rep;
  186.  
  187.   return *this;
  188. }
  189.  
  190. // comparison operators
  191.  
  192. int rcString::operator==(const rcString& s) const { 
  193.   return (strcmp(rep->str, s.rep->str) == 0); 
  194. }
  195.  
  196. int rcString::operator==(const char* s) const { 
  197.   return (strcmp(rep->str, s) == 0); 
  198. }
  199.  
  200. int rcString::operator!=(const rcString& s) const { 
  201.   return (strcmp(rep->str, s.rep->str) != 0); 
  202. }
  203.  
  204. int rcString::operator!=(const char* s) const { 
  205.   return (strcmp(rep->str, s) != 0); 
  206. }
  207.  
  208. int rcString::operator<(const rcString& s) const { 
  209.   return (strcmp(rep->str, s.rep->str) < 0); 
  210. }
  211.  
  212. int rcString::operator<=(const rcString& s) const { 
  213.   return (strcmp(rep->str, s.rep->str) <= 0); 
  214. }
  215.  
  216. int rcString::operator>(const rcString& s) const { 
  217.   return (strcmp(rep->str, s.rep->str) > 0); 
  218. }
  219.  
  220. int rcString::operator>=(const rcString& s) const { 
  221.   return (strcmp(rep->str, s.rep->str) >= 0); 
  222. }
  223.  
  224. // concatenation
  225.  
  226. rcString operator+(const rcString& x, const char* y)
  227. {
  228.   char* buf = new char[x.length() + strlen(y) + 1];
  229.   strcpy(buf, x.chars());
  230.   strcat(buf, y);
  231.  
  232.   return rcString(&buf); // call the private constructor
  233. }  
  234.  
  235. rcString operator+(const char* x, const rcString& y)
  236. {
  237.   char* buf = new char[strlen(x) + y.length() + 1];
  238.   strcpy(buf, x);
  239.   strcat(buf, y.chars());
  240.  
  241.   return rcString(&buf); // call the private constructor
  242. }  
  243.  
  244. rcString operator+(const rcString& x, const rcString& y)
  245. {
  246.   char* buf = new char[x.length() + y.length() + 1];
  247.   strcpy(buf, x.chars());
  248.   strcat(buf, y.chars());
  249.  
  250.   return rcString(&buf); // call the private constructor
  251. }  
  252.   
  253. // stream operators
  254.  
  255. ostream& operator<<(ostream& os, const rcString& s)
  256.   return os << s.chars();
  257. }
  258.